package org.dromara.common.core.utils.file;

import cn.hutool.core.io.FileUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：文件处理工具类
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FileUtils extends FileUtil {

    /**
     * 下载文件名重新编码
     * 设置文件下载的响应头信息
     * 此方法用于配置HTTP响应头，使浏览器能够识别并正确处理文件下载
     * 特别地，它设置了Content-Disposition头，包括文件名和编码方式，确保文件名在不同浏览器中都能正确显示
     * 还设置了Access-Control-Expose-Headers头，以允许跨域请求获取到Content-Disposition头信息，这对于前端判断下载状态十分重要
     *
     * @param response     响应对象
     * @param realFileName 真实文件名
     */
    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) {
        // 对文件名进行编码，确保文件名在不同环境下能被正确解析
        String percentEncodedFileName = percentEncode(realFileName);
        // 构造Content-Disposition头的值，包含附件下载的指示和文件名，同时使用utf-8编码确保文件名的正确解析
        String contentDispositionValue = "attachment; filename=%s;filename*=utf-8''%s".formatted(percentEncodedFileName, percentEncodedFileName);
        // 允许跨域请求获取Content-Disposition头，以便前端能够判断文件是否开始下载
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
        // 设置Content-Disposition头，告诉浏览器接收到的内容应作为附件处理，并提供文件名
        response.setHeader("Content-disposition", contentDispositionValue);
        // 额外设置download-filename头，提供下载文件的名称，辅助部分浏览器正确显示文件名
        response.setHeader("download-filename", percentEncodedFileName);
    }

    /**
     * 百分号编码工具方法
     *
     * @param s 需要百分号编码的字符串
     * @return 百分号编码后的字符串
     */
    public static String percentEncode(String s) {
        // 使用UTF-8编码方式对字符串进行URL编码
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8);
        // 将编码后的加号替换为%20，以符合URL编码的标准
        return encode.replaceAll("\\+", "%20");
    }
}
